package com.ice.app.base.authorization.config;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsUtils;

import com.ice.app.base.authorization.handler.CustomAuthenticationEntryPoint;
import com.ice.app.base.authorization.handler.IceAuthFailureHandler;
import com.ice.app.base.authorization.handler.IceAuthSuccessHandler;
import com.ice.app.base.authorization.handler.MyLogoutSuccessHandler;
import com.ice.app.base.authorization.service.UserSecurityService;

/**
 * spring Security配置安全控制中心
 *
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * 依赖注入自定义的登录成功处理器
     */
    @Autowired
    private IceAuthSuccessHandler iceAuthSuccessHandler;
    /**
     * 依赖注入自定义的登录失败处理器
     */
    @Autowired
    private IceAuthFailureHandler iceAuthFailureHandler;
    
	@Value("${web.ignore.resource}")
	private String allowCallResource;
    
    /**
     * 依赖注入自定义的注销成功的处理器
     */
    @Autowired
    private MyLogoutSuccessHandler myLogoutSuccessHandler;
    
    @Autowired
    private UserSecurityService userSecurityService;
    
    @Resource
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;


    /***注入自定义的CustomPermissionEvaluator*/
    @Bean
    public DefaultWebSecurityExpressionHandler webSecurityExpressionHandler() {
        DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
        handler.setPermissionEvaluator(new CustomPermissionEvaluator());
        return handler;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //这里可启用我们自己的登陆验证逻辑
        auth.userDetailsService(userSecurityService).passwordEncoder(passwordEncoder());
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().
                // 由于使用的是JWT，我们这里不需要csrf
                csrf().disable().authorizeRequests()
                //处理跨域请求中的Preflight请求
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll().and()
                // 基于token，所以不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()

                //所有用户可以访问"/resources"目录下的资源以及访问"/home"和favicon.ico
                .antMatchers(getAllowMatchers()).permitAll()

//                //以"/admin"开始的URL，并需拥有 "ROLE_ADMIN" 角色权限,这里用hasRole不需要写"ROLE_"前缀；
//                .antMatchers("/admin/**").hasRole("ADMIN")
//                //以"/admin"开始的URL，并需拥有 "ROLE_ADMIN" 角色权限和 "ROLE_DBA" 角色,这里不需要写"ROLE_"前缀；
//                .antMatchers("/dba/**").access("hasRole('ADMIN') and hasRole('DBA')")

                //前面没有匹配上的请求，全部需要认证；
                .anyRequest().authenticated()

                .and()
                .formLogin()
                //loginProcessingUrl用于指定前后端分离的时候调用后台登录接口的名称
                .loginProcessingUrl("/jwt/token")
               
                //配置登录成功的自定义处理类
                .successHandler(iceAuthSuccessHandler)
                //配置登录失败的自定义处理类
                .failureHandler(iceAuthFailureHandler)
                .and()
                
                .logout().logoutUrl("/logout")
                //.addLogoutHandler(logoutHandler) //添加自定义的LogoutHandler，默认会添加SecurityContextLogoutHandler
                .logoutSuccessHandler(myLogoutSuccessHandler)
                .deleteCookies("usernameCookie","urlCookie") //在登出同时清除cookies
                ;

        		http.exceptionHandling().authenticationEntryPoint(new CustomAuthenticationEntryPoint());    
        		
		        // 禁用缓存
		        http.headers().cacheControl();
		
		        // 添加JWT filter
		        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

    }
    
    @Bean
    PasswordEncoder passwordEncoder() {
        return new IcePasswordEncoder();
    }
    
    private String [] getAllowMatchers(){
    	if(StringUtils.isEmpty(allowCallResource)) {
    		return new String[0];
    	}
    	return allowCallResource.split(",");
    }
}
